package com.csyf.manager.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.csyf.manager.channel.base.PaymentVo;
import com.csyf.manager.channel.base.ServiceEnum;
import com.csyf.manager.channel.cspay.CspayBiz;
import com.csyf.manager.channel.nmpay.NmPayBiz;
import com.csyf.manager.channel.pddPay.PddPayBiz;
import com.csyf.manager.channel.xiaojifu.XiaojifuBiz;
import com.csyf.manager.dao.SysPayMentDao;
import com.csyf.manager.entity.*;
import com.csyf.manager.exception.ApiValidateException;
import com.csyf.manager.service.*;
import com.csyf.manager.utils.NumberHelpler;
import com.csyf.manager.utils.page.JqGridVo;
import com.csyf.manager.utils.page.PageUtils;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: Enzo
 * @Date: 2018/4/1 15:06
 */

@Slf4j
@Service
public class PayMentBizImpl implements PayMentBiz {


    @Autowired
    private SysTradeTypeBiz sysTradeTypeBiz;

    @Autowired
    private SysPayMentDao sysPayMentDao;

    @Autowired
    private SysPaymentChannelBiz sysPaymentChannelBiz;

    @Autowired
    private SysAgentBalanceBiz sysAgentBalanceBiz;


    @Autowired
    private SysMerchBiz sysMerchBiz;

    @Autowired
    private PayMentBiz payMentBiz;

    @Autowired
    private SysChannelAttrBiz sysChannelAttrBiz;

    @Autowired
    private CspayBiz cspayBiz;

    @Autowired
    private NmPayBiz nmPayBiz;

    @Autowired
    private PddPayBiz pddPayBiz;

    @Autowired
    private XiaojifuBiz xiaojifuBiz;


    @Override
    public Map<String, String> createorder(PaymentVo vo) throws Exception {

        SysChannelAttr sysChannelAttr = sysChannelAttrBiz.findTradeByService(vo.getService());
        if (null == sysChannelAttr) {
            throw new IllegalArgumentException("全局通道未配置");
        }


        SysTradeType sysTradeType = sysMerchBiz.queryTradeType(vo.getMch_id(), vo.getService());

        //判断是否小于最低金额
        log.info("判断是否小于最低金额:{}", sysChannelAttr.getMinMoney());
        BigDecimal total_fee = NumberHelpler.cent2money(vo.getTrans_money());
        if (total_fee.compareTo(sysChannelAttr.getMinMoney()) < 0) {
            throw new IllegalArgumentException("交易金额小于最低金额 :" + sysChannelAttr.getMinMoney());
        }

        //判断是否大于最高金额
        log.info("判断是否大于最高金额{}", sysChannelAttr.getMaxMoney());
        if (total_fee.compareTo(sysChannelAttr.getMaxMoney()) > 0) {
            throw new IllegalArgumentException("交易金额超出交易限制 :" + sysChannelAttr.getMaxMoney());
        }


        SysPayment record = new SysPayment();
        record.setOutTradeNo(vo.getOut_trade_no());
        int count = sysPayMentDao.selectCount(record);
        if (count > 0) {
            throw new IllegalArgumentException("订单号已存在");
        }

        SysPaymentChannel sysPaymentChannel = sysPaymentChannelBiz.handleMerchant(vo.getMch_id(), vo.getService());

        // 校验总余额
        validateTotalMoney(vo.getOut_trade_no(), vo.getMch_id(), sysChannelAttr, vo.getTrans_money(), sysTradeType);
        //validateDFmoney(vo.getOut_trade_no(), vo.getMch_id(), vo.getTrans_money(), vo.getService(), sysPaymentChannel.getFree(), sysChannelAttr);


        SysPayment sysPayment = new SysPayment();

        sysPayment.setMchId(vo.getMch_id());
        sysPayment.setOutTradeNo(vo.getOut_trade_no());
        sysPayment.setAccountName(vo.getAccount_name());
        sysPayment.setBankCard(vo.getBank_card());
        sysPayment.setBankname(vo.getBank_name());
        sysPayment.setBanklinked(vo.getBank_linked());
        sysPayment.setTransmoney(NumberHelpler.cent2money(vo.getTrans_money()));
        sysPayment.setPayStatus("1");
        sysPayment.setCreateTime(new Date());

        ServiceEnum serviceEnum = ServiceEnum.valueOf(vo.getService());
        Integer flag = sysChannelAttr.getFlag();
        if (2 == flag) {
            sysPayment.setPayType("1");
        } else {
            sysPayment.setPayType("2");
        }

        sysPayment.setService(vo.getService());
        String srcMchId = "";

        srcMchId = sysPaymentChannel.getMerchantNo();
        sysPayment.setFree(sysTradeType.getRate());
        sysPayment.setSrcMchId(srcMchId);
        sysPayMentDao.insertSelective(sysPayment);

        Map<String, String> map = new HashMap<>();
        try {
            switch (serviceEnum) {
                case NM_ALI_DF_DZ:
                case NM_ALI_DF_NO:
                    map = nuomiPayment(vo, srcMchId);
                    break;
                case PDD_ALI_DF_NO:
                case PDD_ALI_DF_DZ:
                case PDD_WX_DF_NO:
                case PDD_WX_DF_DZ:
                    map = pddPayment(vo, srcMchId);
                    break;
                case XJ_ALI_DF_NO:
                case XJ_ALI_DF_DZ:
                    map = xiaojiPayment(vo, srcMchId);
                    break;
            }

        } catch (ApiValidateException e) {
            doFail(vo.getOut_trade_no(), e.getMessage());
            map.put("code", "2");
            map.put("message", e.getMessage());
            e.printStackTrace();
            log.error("[{}]代付失败，失败原因={}", vo.getOut_trade_no(), e.getMessage());
        } catch (Exception e) {
            //doFail(vo.getOut_trade_no(), e.getMessage());
            map.put("code", "1");
            map.put("message", "代付中");
            e.printStackTrace();
            log.error("[{}]查询代付失败，失败原因={}", vo.getOut_trade_no(), e.getMessage());
        }
        return map;
    }

    private Map<String, String> nuomiPayment(PaymentVo vo, String srcMchId) throws Exception {
        Map<String, String> hashMap = new HashMap<>();
        Map<String, String> rspMap = nmPayBiz.dodfpay(vo, srcMchId);
        log.info("[{}]SeYe支付代付返回{}", vo.getOut_trade_no(), rspMap);
        hashMap.put("code", "1");
        hashMap.put("message", "代付中");
        return hashMap;
    }

    /**
     * 小机支付宝
     *
     * @param vo
     * @param srcMchId
     * @return
     */
    private Map<String, String> xiaojiPayment(PaymentVo vo, String srcMchId) {
        Map<String, String> hashMap = new HashMap<>();
        xiaojifuBiz.dodfpay(vo, srcMchId);
        hashMap.put("code", "1");
        hashMap.put("message", "代付中");
        return hashMap;
    }

    /**
     * 拼多多 支付宝、微信
     * @return
     */
    private Map<String, String> pddPayment(PaymentVo vo, String srcMchId) {
        Map<String, String> hashMap = new HashMap<>();
        pddPayBiz.dodfpay(vo, srcMchId);
        hashMap.put("code", "1");
        hashMap.put("message", "代付中");
        return hashMap;
    }


    private Map<String, String> ecPayment(PaymentVo vo, String srcMchId) throws ApiValidateException {
        HashMap<String, String> hashMap = new HashMap<>();
        Map<String, String> resultMap = cspayBiz.dodfpay(vo, srcMchId);

        String tradeStatus = resultMap.get("tradeStatus");
        String tradeMessage = resultMap.get("tradeMessage");
        hashMap.put("code", "1");
        hashMap.put("message", "代付中");

        return hashMap;
    }


    private void ordersuccess(Map hashMap, String orderId, String srcOrderId, String code, String message) {
        doSuccess(orderId, srcOrderId, code + "|" + message);
        hashMap.put("code", "3");
        hashMap.put("message", message);
    }

    private void orderunknow(Map hashMap, String orderId, String code, String message) {
        doUnkunow(orderId, code + "|" + message);
        hashMap.put("code", "1");
        hashMap.put("message", message);
    }

    private void orderunknow(Map hashMap, String orderId, String srcOrderId, String code, String message) {
        doUnkunow(orderId, srcOrderId, code + "|" + message);
        hashMap.put("code", "1");
        hashMap.put("message", message);
    }

    private void orderdofaile(Map hashMap, String orderId, String message) {
        doFail(orderId, message);
        hashMap.put("code", "2");
        hashMap.put("message", message);
    }


    @Override
    public List<SysPayment> queryunknowOrder() {
        SysPayment record = new SysPayment();
        record.setPayStatus("1");
        return sysPayMentDao.select(record);
    }

//    @Override
//    public Map queryChannelOrder(String orderNo) throws Exception {
//
//        SysPayment sysPayment = sysPayMentDao.selectByPrimaryKey(orderNo);
//
//        return dfAdvanceBiz.doQuery(sysPayment.getOutTradeNo(), sysPayment.getMchId(), sysPayment.getSrcMchId(), sysPayment.getCreateTime());
//    }

    @Override
    public void doSuccess(String orderNo, String src_reason) {
        doSuccess(orderNo, null, src_reason);
    }


    @Override
    public void doSuccess(String orderNo, String src_order, String src_reason) {
        SysPayment sysPayment = new SysPayment();
        sysPayment.setOutTradeNo(orderNo);
        SysPayment sysPayment1 = sysPayMentDao.selectOne(sysPayment);
        if (null != sysPayment1) {

            if (!"3".equals(sysPayment1.getPayStatus())) {
                sysPayment.setPayStatus("3");
                sysPayment.setSrcReason(src_reason);
                sysPayment.setPayTime(new Date());
                sysPayment.setSrcOrderno(src_order);
                sysPayMentDao.updateByPrimaryKeySelective(sysPayment);
            } else {
                log.info("[{}]   该笔订单已经交易成功", orderNo);
            }
        }


    }

    @Override
    public void doFail(String orderNo, String src_reason) {
        //做三次处理

        SysPayment record = new SysPayment();
        record.setOutTradeNo(orderNo);
        SysPayment sysPayment1 = sysPayMentDao.selectOne(record);
        if (null == sysPayment1) {

        } else {

            SysPayment sysPayment = new SysPayment();
            sysPayment.setOutTradeNo(orderNo);
            sysPayment.setPayStatus("2");
            sysPayment.setSrcReason(src_reason);
            sysPayMentDao.updateByPrimaryKeySelective(sysPayment);


        }
    }

    @Override
    public void doUnkunow(String orderNo, String src_reason) {
        SysPayment sysPayment = new SysPayment();
        sysPayment.setOutTradeNo(orderNo);
        sysPayment.setPayStatus("1");
        sysPayment.setSrcReason(src_reason);
        sysPayMentDao.updateByPrimaryKeySelective(sysPayment);
    }

    @Override
    public JqGridVo queryOrderByUserId(SysPayment vo, Integer page, Integer rows) {
        PageHelper.startPage(page, rows);
        PageHelper.orderBy("create_time desc");

        Example example = new Example(SysPayment.class);
        Example.Criteria criteria = example.createCriteria();
        PageUtils.andEqualTo(criteria, "mchId", vo.getMchId());
        PageUtils.andEqualTo(criteria, "srcMchId", vo.getSrcMchId());
        PageUtils.andEqualTo(criteria, "outTradeNo", vo.getOutTradeNo());
        PageUtils.andEqualTo(criteria, "service", vo.getService());
        PageUtils.andBetweenDateToDate(criteria, "createTime", vo.getCreateTimeString(), vo.getEndTimeString());
        PageUtils.andEqualTo(criteria, "payType", vo.getPayType());
        PageUtils.andEqualTo(criteria, "payStatus", vo.getPayStatus());
        PageUtils.andEqualTo(criteria, "bankCard", vo.getBankCard());
        List<SysPayment> select = sysPayMentDao.selectByExample(example);
        JqGridVo jqGridVo = PageUtils.pasrJqGrid(select);

        BigDecimal totalFee = sysPayMentDao.queryTotalFeeByCondition(vo);
        JSONObject jsonObj = new JSONObject();
        jsonObj.put("service", "总计：");
        jsonObj.put("transmoney", totalFee);
        jqGridVo.setUserdata(jsonObj);
        return jqGridVo;
    }

    /**
     * 查询代付订单总金额
     *
     * @return
     */
    @Override
    public int queryPaymentCountByDay(String mch_id) {
        String timeStr = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        int dfCount = sysPayMentDao.queryDfCount(mch_id, timeStr);
        return dfCount;
    }

    @Override
    public SysPayment queryPaymentByOrderNo(String mch_id, String orderNo) {
        SysPayment sysPayment = new SysPayment();
        sysPayment.setOutTradeNo(orderNo);
        sysPayment.setMchId(mch_id);
        return sysPayMentDao.selectOne(sysPayment);
    }

    @Override
    public SysPayment queryPaymentByOrderId(String orderNo) {
        SysPayment sysPayment = new SysPayment();
        sysPayment.setOutTradeNo(orderNo);
        return sysPayMentDao.selectOne(sysPayment);
    }

    /**
     * 校验总余额
     * 总余额 = 可用余额 + 垫资余额
     */
    private void validateTotalMoney(String out_trade_no, String mch_id, SysChannelAttr sysChannelAttr, String trans_money, SysTradeType sysTradeType) throws ApiValidateException {

        String service = sysChannelAttr.getService();
        String balanceName = sysChannelAttr.getBalanceName();
        BigDecimal free = sysTradeType.getRate();

        // 可用余额
        SysChannelAttr noService = sysChannelAttrBiz.findNoServiceByBalanceName(balanceName);
        BigDecimal tradeBalance = sysAgentBalanceBiz.queryAvailableBalance(mch_id, balanceName, new String[]{noService.getService()});

        // 垫资余额
        BigDecimal dzBalance = BigDecimal.ZERO;

        SysChannelAttr dzService = sysChannelAttrBiz.findDZServiceByBalanceName(balanceName);
        if (null != dzService) {
            List<SysChannelAttr> tradeByBalanceName = sysChannelAttrBiz.findTradeByBalanceName(balanceName);
            String[] trandeService = new String[tradeByBalanceName.size()];
            for (int i = 0; i < tradeByBalanceName.size(); i++) {
                trandeService[i] = tradeByBalanceName.get(i).getService();
            }

            dzBalance = sysAgentBalanceBiz.queryTodayProfit(mch_id, trandeService, new String[]{dzService.getService()}, dzService.getRate().toString());
        }

        // 总余额
        BigDecimal totalMoney = NumberHelpler.add(tradeBalance, dzBalance);

        // 代付金额
        BigDecimal transMoney = NumberHelpler.add(NumberHelpler.cent2money(trans_money), free);
        log.info("代付订单号[{}],商户号[{}],可用余额[{}],垫资余额[{}],总余额[{}],代付总金额[{}]", out_trade_no, mch_id, tradeBalance, dzBalance, totalMoney, transMoney);
        if (transMoney.compareTo(totalMoney) > 0) {
            log.error("代付订单号[{}],商户号[{}],可用余额[{}],垫资余额[{}],总余额[{}],代付总金额[{}]", out_trade_no, mch_id, tradeBalance, dzBalance, totalMoney, transMoney);
            throw new ApiValidateException("代付资金不足");
        }
    }


    private void validateDFmoney(String out_trade_no, String mch_id, String trans_money, String service, BigDecimal free, SysChannelAttr sysChannelAttr) throws ApiValidateException {

        BigDecimal totalprofit = BigDecimal.ZERO;
        //ServiceEnum serviceEnum = ServiceEnum.valueOf(service);
//        switch (serviceEnum) {
//
//            default:
//                log.info("默认交易方式：{}", sysChannelAttr.getService());
//                //余额金额验证
//                if (1 == sysChannelAttr.getFlag()) {
//                    log.info("[{}]余额金额验证", sysChannelAttr.getService());
//
//                    String[] balanceserver = {sysChannelAttr.getService()};
//                    totalprofit = sysAgentBalanceBiz.queryAvailableBalance(mch_id, sysChannelAttr.getBalanceName(), balanceserver);
//
//                } else if (2 == sysChannelAttr.getFlag()) {
//                    log.info("[{}]垫资金额验证", sysChannelAttr.getService());
//
//                    List<SysChannelAttr> tradeByBalanceName = sysChannelAttrBiz.findTradeByBalanceName(sysChannelAttr.getBalanceName());
//                    String[] trandeService = new String[tradeByBalanceName.size()];
//                    for (int i = 0; i < tradeByBalanceName.size(); i++) {
//                        trandeService[i] = tradeByBalanceName.get(i).getService();
//                    }
//                    String[] balancedfServices = {sysChannelAttr.getService()};
//                    totalprofit = sysAgentBalanceBiz.queryTodayProfit(mch_id, trandeService, balancedfServices, sysChannelAttr.getRate().toString());
//                } else {
//                    log.info("非余额和垫资代付:{}", sysChannelAttr.getService());
//                    totalprofit = BigDecimal.ZERO;
//                }
//                break;
//
//        }

        log.info("默认交易方式：{}", sysChannelAttr.getService());
        //余额金额验证
        if (1 == sysChannelAttr.getFlag()) {
            log.info("[{}]余额金额验证", sysChannelAttr.getService());

            String[] balanceserver = {sysChannelAttr.getService()};
            totalprofit = sysAgentBalanceBiz.queryAvailableBalance(mch_id, sysChannelAttr.getBalanceName(), balanceserver);

        } else if (2 == sysChannelAttr.getFlag()) {
            log.info("[{}]垫资金额验证", sysChannelAttr.getService());

            List<SysChannelAttr> tradeByBalanceName = sysChannelAttrBiz.findTradeByBalanceName(sysChannelAttr.getBalanceName());
            String[] trandeService = new String[tradeByBalanceName.size()];
            for (int i = 0; i < tradeByBalanceName.size(); i++) {
                trandeService[i] = tradeByBalanceName.get(i).getService();
            }
            String[] balancedfServices = {sysChannelAttr.getService()};
            totalprofit = sysAgentBalanceBiz.queryTodayProfit(mch_id, trandeService, balancedfServices, sysChannelAttr.getRate().toString());
        } else {
            log.info("非余额和垫资代付:{}", sysChannelAttr.getService());
            totalprofit = BigDecimal.ZERO;
        }

        BigDecimal totalmoney = NumberHelpler.add(NumberHelpler.cent2money(trans_money), free);
        log.info("代付订单号[{}]，商户号[{}]，代付资金{}, 可用资金{}", out_trade_no, mch_id, totalmoney, totalprofit);
        if (totalmoney.compareTo(totalprofit) > 0) {
            log.error("[{}] 代付资金不足", mch_id);
            throw new ApiValidateException("代付资金不足");
        }

    }


    @Override
    public void doUnkunow(String orderNo, String src_order, String src_reason) {
        SysPayment sysPayment = new SysPayment();
        sysPayment.setOutTradeNo(orderNo);
        sysPayment.setPayStatus("1");
        sysPayment.setSrcReason(src_reason);
        sysPayment.setSrcOrderno(src_order);
        sysPayMentDao.updateByPrimaryKeySelective(sysPayment);
    }
}
